
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>svg滤镜制作-故障波动特效</title>
</head>
<style>
  .img-warpper {
    width: 300px;
    height: 500px;
  }

  .img-warpper>img {
    width: 100%;
    height: 100%;
    filter: url(#svg-filter);
  }
</style>

<body>
  <div class="img-warpper">
    <img src="./1.jpeg" alt="" id="img">
    <svg style="display: none;">
      <defs>
        <filter id="svg-filter" x="-20%" y="-20%" width="140%" height="140%" filterUnits="objectBoundingBox"
          primitiveUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
          <feTurbulence id="feTurbulence" type="turbulence" baseFrequency="0 0" numOctaves="2" seed="2"
            stitchTiles="stitch" x="0%" y="0%" width="100%" height="100%" result="turbulence" />
          <feDisplacementMap in="SourceGraphic" in2="turbulence" scale="30" xChannelSelector="R" yChannelSelector="B"
            x="0%" y="0%" width="100%" height="100%" result="displacementMap" />
        </filter>
      </defs>
    </svg>
  </div>
</body>

</html>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js"></script>
<script>
  // 生成svg故障波纹 filter 地址 https://yoksel.github.io/svg-filters/#/
  const tb = document.getElementById('feTurbulence')
  const val = {
    value: 0
  }
  const tl = new gsap.timeline({
    paused: true,// 开始暂停
    onUpdate() {
      tb.setAttribute('baseFrequency', `0 ${val.value}`)
    }
  })
  tl.to(val, {
    value: 0.4,
    duration: 0.2
  })
  tl.to(val, {
    value: 0,
    duration: 0.2
  })
  const img = document.getElementById('img')
  img.onmouseenter = () => {
    tl.restart()
  }
</script>